package br.cefetpe.tsi.game.desktop.ui.gui;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Point2D;

import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

import br.cefetpe.tsi.game.base.Disk;
import br.cefetpe.tsi.game.base.Roullette;
import br.cefetpe.tsi.game.base.views.HexagonView;
import br.cefetpe.tsi.game.base.views.TriangleView;

public class RoullettePanel extends JPanel {

	private static final long serialVersionUID = -9079084463043967833L;

	private Roullette roullette = null;

	private HexagonView hv = null;
	
	private int fromDiskIndex;
	
	private int toDiskIndex;
	
	private Point2D.Double center = null;

	private JPopupMenu popupMenu = null;

	public RoullettePanel() {
		super();
		setRoullete(new Roullette());
		setSize(500, 500);
		center = new Point2D.Double();
		center.x = getSize().getWidth() / 2;
		center.y = getSize().getHeight() / 2;
		hv = new HexagonView(center, 50);
		initializePopUpMenu();		
		addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				System.out.println("[" + e.getPoint().x + ", " + e.getPoint().y
						+ "]");
				for (int i = 0; i < hv.getHexagon().length; i++) {
					
					System.out.print("[" + i +"]");
					//System.out.println(hv.getHexagon()[i].contains(e.getPoint()));
					if (hv.getHexagon()[i].contains(e.getPoint())) {
						rotateDisk(i);
					}
				}
				verifyPopUpTrigger(e);
				verifyChangeOfDisks(e);
			}			
			
			private void verifyChangeOfDisks(MouseEvent e) {
				Point2D.Double pStart = new Point2D.Double(e.getPoint().getX(),e.getPoint().getY());
				Point2D.Double pEnd= new Point2D.Double(e.getLocationOnScreen().getX(),e.getLocationOnScreen().getY());
				int hexStart = 0;
				int hexEnd = 0;
				for (int i = 0; i < hv.getHexagon().length; i++) {
					if (hv.getHexagon()[i].contains(pStart) ) {
						hexStart = i;
					}
					if (hv.getHexagon()[i].contains(pEnd) ) {
						hexEnd = i;
					}
				}
				if ( hexStart != hexEnd ){
					changeDisks(hexStart, hexEnd);
				}
			}

			private void verifyPopUpTrigger(MouseEvent e) {
				if (e.isPopupTrigger() || SwingUtilities.isRightMouseButton(e)) {
					popupMenu.show(e.getComponent(),  e.getX(), e.getY());
				}
			}			

			public void mousePressed(MouseEvent e) {
				for (int i = 0; i < hv.getHexagon().length; i++) {					
					if (hv.getHexagon()[i].contains(e.getPoint())) {
						fromDiskIndex = i;
					}
				}
				
			}

			public void mouseReleased(MouseEvent e) {
				for (int i = 0; i < hv.getHexagon().length; i++) {					
					if (hv.getHexagon()[i].contains(e.getPoint())) {
						toDiskIndex = i;
					}
				}
				changeDisks(fromDiskIndex, toDiskIndex);								
			}
			
			});
	}

	private void initializePopUpMenu() {
		popupMenu = new JPopupMenu();
		// Solve Menu Item
		JMenuItem jmiSolve = new JMenuItem();
		jmiSolve.setText("Resolver");
		jmiSolve.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				goSolving();
			}
		});

		// Scramble Menu Item
		JMenuItem jmiScramble = new JMenuItem();
		jmiScramble.setText("Embaralhar");
		jmiScramble.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				scrambleRoullette();
			}
		});

		// Open roullette
		JMenuItem jmiOpenGame = new JMenuItem();
		jmiOpenGame.setText("Abrir Jogo...");
		jmiOpenGame.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				openRoullette();
			}
		});

		// Save roullette
		JMenuItem jmiSaveGame = new JMenuItem();
		jmiSaveGame.setText("Salvar Jogo...");
		jmiSaveGame.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				saveRoullette();
			}
		});

		// Sobre o jogo
		JMenuItem jmiAbout = new JMenuItem();
		jmiAbout.setText("Sobre");
		jmiAbout.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				AboutDialog ad = new AboutDialog(null);
				ad.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
			}
		});
		popupMenu.add(jmiScramble);
		popupMenu.add(jmiSolve);
		popupMenu.addSeparator();
		popupMenu.add(jmiOpenGame);
		popupMenu.add(jmiSaveGame);
		popupMenu.addSeparator();
		popupMenu.add(jmiAbout);

	}

	public RoullettePanel(Roullette roullette) {
		super();
		setRoullete(roullette);
		setSize(500, 500);
	}

	@Override
	public void paint(Graphics g) {
		Graphics2D g2d = (Graphics2D) g;
		TriangleView tv = new TriangleView(center, 50);
		tv.drawRoullette(g2d, getRoullete());		
	}

	public void redraw() {
		repaint();
	}

	public void rotateDisk(int diskNo) {
		getRoullete().rotateDisk(diskNo);
		redraw();
	}

	public void rotateDisk(int diskNo, int step) {
		getRoullete().rotateDisk(diskNo, step);
		redraw();
	}

	public void changeDisks(int diskFrom, int diskTo) {
		getRoullete().changeDisks(diskFrom, diskTo);
		redraw();
	}

	public void setDisk(int positionInRoullette, Disk d) {
		getRoullete().getDiskSet()[positionInRoullette] = d;
		redraw();
	}

	public void scrambleRoullette() {
		getRoullete().setDiskSet(getRoullete().scramble());
		redraw();
	}

	public void saveRoullette() {
		JFileChooser jfc = new JFileChooser();
		jfc.setFileFilter(new ColorRoulletteFileFilter());
		jfc.showSaveDialog(null);
		getRoullete().toXML(getRoullete(), jfc.getSelectedFile().getName());
		JOptionPane.showConfirmDialog(null, "Salvo em: "
				+ jfc.getSelectedFile().getAbsolutePath());
	}

	public void openRoullette() {
		JFileChooser jfc = new JFileChooser();
		jfc.setFileFilter(new ColorRoulletteFileFilter());
		jfc.showOpenDialog(null);
		setRoullete(Roullette.fromXML(jfc.getSelectedFile().getAbsolutePath()));
		redraw();
	}

	public void goSolving() {
		for (int i = 0; i < Roullette.firstMappedSolution().getDiskSet().length; i++) {
			setDisk(i, Roullette.firstMappedSolution().getDiskSet()[i]);
			redraw();
		}
	}

	public Roullette getRoullete() {
		return roullette;
	}

	public void setRoullete(Roullette roullete) {
		this.roullette = roullete;
	}
}
